class drawBoxLine {
  constructor(dataList, container, config) {
    let self = this;
    if (!dataList || !Array.isArray(dataList.fxp_dz_lst)) {
      throw new Error("请检查数据~");
    }
    this.direction = dataList.direction == "left" ? -1 : 1; //-1往左，1往右
    this.distance = config?.distance || 45; //不能小于此值，否则会遮住
    this.boxWidth = config?.boxWidth || 100;
    this.boxInfoDis = 5; //固定值
    this.movex = config?.move || 60;
    this.rectsGroup = null;
    this.svgContainer = null;
    this.dataList = dataList;
    this.container = container;
    this.background = config?.background || "black";
    this.lineColor = config?.lineColor || "#ffffff";
    this.textColor = config?.textColor || "red";
    this.circleColor = config?.circleColor || "blue";
    this.configData = {
      width: config?.width || 1500,
      height: config?.height || 800,
      boxNum: dataList.box_max_size + 1 || 6,
      duanziDis: this.distance, //端子间距,可以修改
      duanziNum: dataList.fxp_dz_lst.length, //端子个数
      boxHeight: (dataList.fxp_dz_lst.length - 1) * self.distance + 20, //箱盒高度，参数可修改
      boxWidth: this.boxWidth, //箱盒宽度,可以修改
      boxInfoDis: this.boxInfoDis, //箱盒信息高度,可以修改
      boxInfoLine: {},
      duanziList: [
        {
          name: "",
          position: [
            this.boxWidth / 2,
            this.boxInfoDis * 3 + 0 * this.distance,
          ], //端子坐标
          path: [
            [-this.movex / 2, this.boxInfoDis * 3 + 0 * this.distance],
            [
              this.boxWidth + this.movex / 2,
              this.boxInfoDis * 3 + 0 * this.distance,
            ],
          ],
        },
      ],
      boxMove: [(this.movex + this.boxWidth) * this.direction, 0],
    };
    this.init();
  }
  init() {
    this.svgContainer = d3
      .select(`#${this.container}`)
      .append("svg")
      .attr("id", "svg-meta2")
      .attr("width", this.configData.width)
      .attr("height", this.configData.height)
      .attr("style", `background:${this.background}`);
    this.rectsGroup = this.svgContainer
      .append("g")
      .attr("class", "rects-group");
    this.fit();
  }
  fit() {
    let self = this;

    let minx =
      this.direction < 0
        ? -(
            (self.configData.boxNum - 2) * self.configData.boxWidth +
            (self.configData.boxNum - 1) * self.movex
          )
        : -(self.configData.boxWidth + 2 * self.movex);
    let maxx =
      this.direction < 0
        ? self.configData.boxWidth * 2 + 2 * self.movex
        : (self.configData.boxNum - 1) * self.configData.boxWidth +
          self.configData.boxNum * self.movex;

    let miny = 0;
    let maxy =
      this.configData.duanziNum * this.configData.duanziDis +
      this.boxInfoDis * 3;

    let width = maxx - minx;

    let height = maxy - miny;
    let scaleW = this.configData.width / width;
    let scaleH = this.configData.height / height;
    let scale = scaleW < scaleH ? scaleW : scaleH;

    let offsetX =
      0 - minx * scale + (this.configData.width - width * scale) / 2;

    let offsetY =
      0 - miny * scale + (this.configData.height - height * scale) / 2 + 10;
    let zoom = d3
      .zoom()
      .scaleExtent([0.1, 100])
      .on("zoom", function () {
        scale = d3.event.transform.k;
        offsetX = d3.event.transform.x;
        offsetY = d3.event.transform.y;
        if (!isNaN(d3.event.transform.k))
          self.rectsGroup.attr("transform", d3.event.transform);
      });

    let pathover = this.svgContainer.call(zoom);
    pathover
      .transition()
      .duration(400)
      .call(
        zoom.transform,
        d3.zoomIdentity.translate(offsetX, offsetY).scale(scale)
      );
    //   开始处理数据
    this.handleData(this.dataList);
  }

  // 原始数据预处理
  handleData(dataList) {
    // 分线盘
    let dz_list = dataList.fxp_dz_lst;
    let boxinfo = {
      id: dataList.fxp_name + dataList.fxp_info,
      name: dataList.fxp_name + "(" + dataList.fxp_info + ")",
      cable_info: "",
    };
    this.preHandle(dz_list, [0, 0], boxinfo);
    // 组合柜
    let pa_list = dataList.fxp_parent_box.zhg_duanzi_lst;
    let move = [(this.boxWidth + this.movex) * -1 * this.direction, 0];
    let zhginfo = {
      id: dataList.fxp_parent_box.zhg_name + dataList.fxp_parent_box.zhg_info,
      name:
        dataList.fxp_parent_box.zhg_name +
        "(" +
        dataList.fxp_parent_box.zhg_info +
        ")",
      cable_info: "",
    };
    this.preHandle(pa_list, move, zhginfo);

    // 子箱盒
    dataList.fxp_to_box.child_box_lst.push({
      begin_box_name: "",
      box_info: dataList.fxp_info,
      box_name: dataList.fxp_name,
      cable_info: "",
      dz_lst: dataList.fxp_dz_lst,
    });

    this.recursion(dataList.fxp_to_box.child_box_lst, dataList.fxp_name, 1, 0);
  }
  recursion(list, parentName, num, ynum) {
    let realList = list;
    // 横向偏移
    let n = num;

    let child = realList.filter((item) => item.begin_box_name == parentName);
    let parent = realList.filter((i) => i.box_name == parentName)[0];
    // 计算上下偏移
    let childList = child.map((item) => {
      let up =
        ynum +
        parent.dz_lst.findIndex(
          (ele) =>
            ele.next_box + "" + ele.next_dz ==
            item.box_name + "" + item.dz_lst[0].dz_name
        );
      return { ...item, ynum: up };
    });

    // 根据计算结果绘制子箱盒
    childList.forEach((item) => {
      this.preHandle(
        item.dz_lst,
        [
          (this.boxWidth + this.movex) * this.direction * n,
          item.ynum * this.configData.duanziDis,
        ],
        {
          id: item.box_name + item.box_info,
          name: item.box_name + "(" + item.box_info + ")",
          cable_info: item.cable_info,
        }
      );
    });
    n++;
    // 遍历每个子箱盒
    childList.forEach((item) => {
      this.recursion(realList, item.box_name, n, item.ynum);
    });
  }
  preHandle(dz_lst, move, boxinfo) {
    this.configData.boxInfoLine = {};
    if (!Array.isArray(dz_lst)) return;
    this.configData.duanziNum = dz_lst.length;
    this.configData.boxHeight =
      (this.configData.duanziNum - 1) * this.distance +
      this.boxInfoDis * 2 +
      20;
    this.configData.boxInfoLine[boxinfo.name] = [
      [0, 1 * this.boxInfoDis],
      [this.boxWidth, 1 * this.boxInfoDis],
    ];
    // Object.keys(boxinfo).forEach((i, index) => {
    //   configData.boxInfoLine[boxinfo[i]] = [
    //     [0, (1 + index) * boxInfoDis],
    //     [boxWidth, (1 + index) * boxInfoDis],
    //   ];
    // });
    this.configData.boxMove = [move[0], move[1]];
    this.configData.duanziList = dz_lst.map((item, index) => {
      return {
        ...item,
        name: item.dz_name,
        position: [
          this.boxWidth / 2,
          this.boxInfoDis * 3 + index * this.distance,
        ],
        path: [
          [-this.movex / 2, this.boxInfoDis * 3 + index * this.distance],
          [
            this.boxWidth + this.movex / 2,
            this.boxInfoDis * 3 + index * this.distance,
          ],
        ],
      };
    });
    this.renderRects("s" + boxinfo.id, boxinfo.cable_info);
  }
  renderRects(id, name) {
    let line_generator = d3.line();

    this.rectsGroup
      .append("g")
      .attr(
        "transform",
        `translate(${this.configData.boxMove[0]}, ${this.configData.boxMove[1]})`
      )
      .attr("id", id);
    // 画矩形,箱盒
    this.rectsGroup
      .select(`#${id}`)
      .append("g")
      .attr("id", "reacts")
      .append("rect")
      .attr("width", this.configData.boxWidth)
      .attr("height", this.configData.boxHeight)
      .attr("x", 0)
      .attr("y", 0)
      .attr("stroke", this.lineColor)
      .attr("fill", "transparent");
    //画cable_info
    this.rectsGroup
      .select(`#${id}`)
      .append("text")
      .text(name)
      .attr(
        "x",
        this.direction > 0 ? -(this.movex / 2) : this.movex / 2 + this.boxWidth
      )
      .attr("y", -5)
      .attr("font-size", "10px")
      .attr("fill", this.textColor);
    //画两条线，箱盒信息

    Object.keys(this.configData.boxInfoLine).forEach((info, index) => {
      // rectsGroup
      //   .select(`#${id}`)
      //   .select("#reacts")
      //   .append("path")
      //   .attr("d", line_generator(configData.boxInfoLine[info]));
      this.rectsGroup
        .select(`#${id}`)
        .select("#reacts")
        .append("text")
        .text(info)
        .attr("dx", this.boxWidth / 2)
        .attr("dy", index * this.boxInfoDis - 5)
        .attr("font-size", "10px")
        .attr("fill", this.textColor);
    });

    //画线，线束及线束名称
    this.configData.duanziList.forEach((pat) => {
      if (pat.dz_name) {
        let position =
          this.direction == 1
            ? [pat.path[1][0], pat.path[0][1] - 5]
            : [pat.path[0][0], pat.path[0][1] - 5];
        this.rectsGroup
          .select(`#${id}`)
          .select("#reacts")
          .append("path")
          .attr("d", line_generator(pat.path))
          .attr("class", "xianshu");
        this.rectsGroup
          .select(`#${id}`)
          .select("#reacts")
          .append("text")
          .text(pat.next_xs || pat.use_info)
          .attr("dx", position[0] - 10)
          .attr("dy", position[1])
          .attr("font-size", "10px")
          .attr("fill", this.textColor);
      }
    });
    //设置线的外观，箱盒颜色
    this.rectsGroup
      .select(`#${id}`)
      .selectAll("path")
      .attr("stroke", this.lineColor)
      .attr("stroke-width", "1px");
    this.renderCircle(id);
  }

  renderCircle(id) {
    // 画点，端子
    this.rectsGroup
      .select(`#${id}`)
      .select("#reacts")
      .append("g")
      .attr("class", "point-circle")
      .selectAll("circle")
      .data(this.configData.duanziList)
      .join("circle")
      .attr("class", "points")
      .attr("id", (d) => d.name)
      .attr("cx", (d) => d.position[0])
      .attr("cy", (d) => d.position[1])
      .attr("fill", (d) => (d.dz_name ? `${this.circleColor}` : "transparent"))
      .attr("r", 2);

    // 在点上画文字，端子名称
    this.rectsGroup
      .select(`#${id}`)
      .select("#reacts")
      .attr("class", "point-text")
      .append("g")
      .selectAll()
      .data(this.configData.duanziList)
      .join("text")
      .text(function (d) {
        return d.name;
      })
      .attr("dx", (d) => d.position[0] - 8)
      .attr("dy", (d) => d.position[1] - 5)
      .attr("font-size", "10px")
      .attr("fill", this.textColor);
  }
}
